package com.gitee.wsl.ext.array

import com.gitee.wsl.ext.base.MAX_RADIX
import com.gitee.wsl.ext.base.MIN_RADIX
import com.gitee.wsl.ext.base.buildFrom
import com.gitee.wsl.ext.list.truncate


/**
 * return a BigEndian bigEndianInteger built this way:
 * |---------------------------------------|
 * | byte[0] | byte[1] | byte[2] | byte[3] |
 * |_______________________________________|
 *
 * [ByteArray.size] must be between 0 and  [Int.SIZE_BYTES]
 */
fun ByteArray.toBigEndianInteger(): Int {
    require(this.size <= Int.SIZE_BYTES) {
        "This byte array must not be longer than ${Int.SIZE_BYTES}"
    }

    var bigEndian = 0

    this.reversedArray().forEachIndexed { index, byte ->
        bigEndian = bigEndian.buildFrom(byte, index)
    }

    return bigEndian
}

/**
 * return a LittleEndian bigEndianInteger built this way:
 * |---------------------------------------|
 * | byte[3] | byte[2] | byte[1] | byte[0] |
 * |_______________________________________|
 *
 * [ByteArray.size] must be between 0 and  [Int.SIZE_BYTES]
 */
fun ByteArray.toLittleEndianInteger(): Int {
    require(this.size <= Int.SIZE_BYTES) {
        "This byte array must not be longer than ${Int.SIZE_BYTES}"
    }

    var littleEndian = 0

    this.forEachIndexed { index, byte ->
        littleEndian = littleEndian.buildFrom(byte, index)
    }

    return littleEndian
}

/**
 * Parses the string argument as if it was an int value and returns the result. Throws
 * NumberFormatException if the string does not represent an int quantity. The second argument
 * specifies the radix to use when parsing the value.
 *
 * @param chars a string representation of an int quantity.
 * @param radix the base to use for conversion.
 * @return int the value represented by the argument
 * @throws NumberFormatException if the argument could not be parsed as an int quantity.
 */
@Throws(NumberFormatException::class)
fun CharArray.parseInt( offset: Int, len: Int, radix: Int): Int {

    var offset = offset
    var len = len
    if ( radix < Char.MIN_RADIX || radix > Char.MAX_RADIX) {
        throw NumberFormatException()
    }
    var i = 0
    if (len == 0) {
        throw NumberFormatException("chars length is 0")
    }
    val negative = this[offset + i] == '-'
    if (negative && ++i == len) {
        throw NumberFormatException("can't convert to an int")
    }
    if (negative) {
        offset++
        len--
    }
    return parse(this, offset, len, radix, negative)
}

@Throws(NumberFormatException::class)
private fun parse(chars: CharArray, offset: Int, len: Int, radix: Int, negative: Boolean): Int {
    val max = Int.MIN_VALUE / radix
    var result = 0
    for (i in 0 until len) {
        val digit = chars[i + offset].digitToIntOrNull(radix) ?: -1
        if (digit == -1) {
            throw NumberFormatException("Unable to parse")
        }
        if (max > result) {
            throw NumberFormatException("Unable to parse")
        }
        val next = result * radix - digit
        if (next > result) {
            throw NumberFormatException("Unable to parse")
        }
        result = next
    }
    /*while (offset < len) {

}*/if (!negative) {
        result = -result
        if (result < 0) {
            throw NumberFormatException("Unable to parse")
        }
    }
    return result
}